package me.msz.application.m2copy;

import ch.qos.logback.classic.LoggerContext;
import me.msz.application.m2copy.core.M2RepoCopier;
import org.apache.commons.cli.*;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import me.msz.application.m2copy.constants.CompressAlgorithms;
import me.msz.application.m2copy.constants.ExitCodes;
import me.msz.application.m2copy.constants.OptionsManager;

import java.io.IOException;

public class M2RepoCopyCLI {
    private static Options options = OptionsManager.getOptionsInstance();
    private static Logger logger = LoggerFactory.getLogger(me.msz.application.m2copy.M2RepoCopyCLI.class);
    LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();

    private M2RepoCopyCLI() {}

    public static void main(String[] args) {
        CommandLineParser parser = new DefaultParser();

        boolean isCopyAll = false;
        boolean isOnlyJars = false;
        boolean isNeedCompress = false;
        boolean isVerbose = false;

        String compressAlgoName = CompressAlgorithms.ZIP.toString();
        String srcPath;
        String destPath;

        try {
            CommandLine commandLineParams = parser.parse(options, args);

            if(commandLineParams.hasOption("help") || commandLineParams.getOptions().length == 0) {
                logger.info("Option \"help\" has been set, or no options are specified.");
                showHelp();
                System.exit(ExitCodes.EXIT_SUCCESS.ordinal());
            }

            if(commandLineParams.hasOption("all")) {
                isCopyAll = true;
                logger.info("Option \"all\" has been set.");
            }

            if(commandLineParams.hasOption("jars")) {
                isOnlyJars = true;
                logger.info("Option \"jars\" has been set.");
            }

            if(commandLineParams.hasOption("verbose")) {
                isVerbose = true;
                logger.info("Option \"verbose\" has been set.");
            }

            if(commandLineParams.hasOption("compress")) {
                isNeedCompress = true;
                compressAlgoName = commandLineParams.getOptionValue("compress");
                if(!(StringUtils.equalsAnyIgnoreCase(compressAlgoName, CompressAlgorithms.ZIP.toString(),
                        CompressAlgorithms.SEVERZ.toString(), CompressAlgorithms.GZIP.toString(),
                        CompressAlgorithms.TAR.toString(), CompressAlgorithms.TGZ.toString()))) {
                    logger.info("Option \"compress\" has been set, and the algorithm is " + compressAlgoName + ".");
                } else {
                    logger.error("Option \"compress\" has been set, but the argument " + compressAlgoName +
                            " can't be recognized.");
                    throw new ParseException("Unrecognized argument" + compressAlgoName +
                            "for option: c or compress.");
                }
            }

            if(commandLineParams.hasOption("src")) {
                logger.info("Option \"src\" has been set.");
                srcPath = commandLineParams.getOptionValue("src");
            } else {
                throw new ParseException("Missing required option: s or src.");
            }

            if(commandLineParams.hasOption("dest")) {
                logger.info("Option \"dest\" has been set.");
                destPath = commandLineParams.getOptionValue("dest");
            } else {
                throw new ParseException("Missing required option: d or dest.");
            }

            logger.debug(showCommandLineInfo(commandLineParams));
            M2RepoCopier.getInstance().doCopyRepo(isCopyAll, isOnlyJars, isNeedCompress, isVerbose, compressAlgoName,
                    srcPath, destPath);

        } catch( ParseException exp ) {
            String expInfo = exp.getLocalizedMessage();
            logger.debug("Parsing failed. Reason: " + expInfo);
            ExitCodes exitCode = ExitCodes.EXIT_UNKNOWN_REASON;
            showHelp();
            if(StringUtils.containsIgnoreCase(expInfo, "Missing required option")) {
                exitCode = ExitCodes.EXIT_MISSING_OPTION;
            }
            if(StringUtils.containsIgnoreCase(expInfo, "Missing argument")) {
                exitCode = ExitCodes.EXIT_MISSING_ARGUMENTS;
            }
            if(StringUtils.containsIgnoreCase(expInfo, "Invalid argument")) {
                exitCode = ExitCodes.EXIT_INVALID_ARGUMENTS;
            }
            if(StringUtils.containsIgnoreCase(expInfo, "Unrecognized option")) {
                exitCode = ExitCodes.EXIT_UNRECOGNIZED_OPTION;
            }
            if(StringUtils.containsIgnoreCase(expInfo, "Unrecognized argument")) {
                exitCode = ExitCodes.EXIT_UNRECOGNIZED_ARGUMENTS;
            }

            logger.debug(exitCode.toString());
            System.exit(exitCode.ordinal());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void showHelp() {
        HelpFormatter formatter = new HelpFormatter();
        formatter.printHelp("m2copy", options);
        System.out.println();
    }

    private static String showCommandLineInfo(CommandLine line) {
        StringBuilder buf = new StringBuilder();
        buf.append("Options are : ");
        Option[] enabledOptions = line.getOptions();
        for(Option option : enabledOptions) {
            buf.append(option.toString());
        }

        return buf.toString();
    }

}
